local guiben = fk.CreateSkill{
  name = "dajubei__guiben",
  tags = { Skill.Compulsory }
}

Fk:loadTranslationTable{
  ["dajubei__guiben"] = "归本",
  [":dajubei__guiben"] = "锁定技，一轮内，当你累计使用三种类型的牌后，或当你三个区域内的牌数量均发生变化后，"
  .."若你于此轮未以此法获得过牌，则你获得弃牌堆和场上各一张牌，并从牌堆随机获得一张牌。",

  ["guibenPoxi"] = "归本",
  ["#guibenPoxi"] = "归本：获得弃牌堆和场上各一张牌，并从牌堆随机获得一张牌",

  ["$dajubei__guiben1"] = "",
}

-- Poxi
Fk:addPoxiMethod{
  name = "guibenPoxi",
  prompt = "#guibenPoxi",
  card_filter = Util.TrueFunc,
  feasible = function (selected, data, extra_data)
    local map = {
      { #extra_data.field_cards > 0 },
      { #extra_data.discard_pile > 0 }
    }

    for _, id in ipairs(selected) do
      if table.contains(extra_data.field_cards, id) then
        table.insert(map[1], id)
      else
        table.insert(map[2], id)
      end
    end

    ---@param t table<boolean, any>
    ---@return boolean
    local function canpass(t)
      if t[1] then
        return #t == 2
      else
        return #t == 1
      end
    end

    return table.every(map, canpass)
  end,
  default_choice = function (data, extra_data)
    local ret = {}

    if #extra_data.discard_pile > 0 then
      table.insert(ret, extra_data.discard_pile[1])
    end

    if #extra_data.field_cards > 0 then
      table.insert(ret, extra_data.field_cards[1])
    end
    return ret
  end,
}

--- obtain cards
---@param player ServerPlayer
local function getRandomCards(player)
  local room = player.room
  local card_data = {}
  local field_cards = {}
  local discard_pile = {}

  if #room.discard_pile > 0 then
    table.insert(card_data, {"pile_discard", room.discard_pile})
    table.insertTable(discard_pile, room.discard_pile)
  end

  for _, p in ipairs(room.alive_players) do
    if #p:getCardIds("ej") > 0 then
      table.insert(card_data, {p.general, p:getCardIds("ej")})
      table.insertTable(field_cards, p:getCardIds("ej"))
    end
  end

  local ret = room:askToPoxi(player, {
    poxi_type = "guibenPoxi",
    cancelable = false,
    data = card_data,
    extra_data = {
      skillName = "dajubei__guiben",
      field_cards = field_cards,
      discard_pile = discard_pile,
    }
  })

  if #room.draw_pile > 0 then
    table.insert(ret, table.random(room.draw_pile, 1))
  end
  room:obtainCard(player, ret, true, fk.ReasonJustMove, player, guiben.name)
end

-- 3 types used
guiben:addEffect(fk.CardUseFinished, {
  anim_type = "drawcard",
  can_trigger = function (self, event, target, player, data)
    if not player:hasSkill(guiben.name) or player ~= target then return end
    local types = {}

    ---@param e GameEvent.UseCard
    ---@return any
    local filter = function (e)
      if e.data.from == player then table.insertIfNeed(types, e.data.card:getTypeString()) end
      if #types == 3 then return true end
    end

    player.room.logic:getEventsOfScope(GameEvent.UseCard, 1, filter, Player.HistoryRound)
    return #types == 3
  end,
  on_cost = Util.TrueFunc,
  on_use = function (self, event, target, player, data)
    player.room:invalidateSkill(player, guiben.name, "-round")
    getRandomCards(player)
  end,
})

-- 3 areas changed
guiben:addEffect(fk.AfterCardsMove, {
  anim_type = "drawcard",
  can_trigger = function (self, event, target, player, data)
    if not player:hasSkill(guiben.name) then return end
    local areas = {}

    ---@param e GameEvent.MoveCards
    ---@return any
    local filter = function (e)
      for _, move in ipairs(e.data) do
        if move.from == player then
          for _, info in ipairs(move.moveInfo) do
            if info.fromArea < 4 then
              table.insertIfNeed(areas, info.fromArea)
            end
          end
        elseif move.to == player and move.toArea < 4 then
          table.insertIfNeed(areas, move.toArea)
        end
      end
      if #areas == 3 then return true end
    end

    player.room.logic:getEventsOfScope(GameEvent.MoveCards, 1, filter, Player.HistoryRound)
    return #areas == 3
  end,
  on_cost = Util.TrueFunc,
  on_use = function (self, event, target, player, data)
    player.room:invalidateSkill(player, guiben.name, "-round")
    getRandomCards(player)
  end
})

return guiben